【X68000(Z)アセンブラ講座 第011回 BGグラフィックス画面】 2025/02/22 こんにちは!! 今回は画面解像度256×256ピクセルで BG画面を表示するプログラムを書きます。 BG画面はゲームのマップや背景や文字表示などに使われていますね。 破線の内側を'BG_SAMP.s'と言うファイル名で保存して下さい。 ------------------------------------------------------------------------------------------------   ******************************************************************************** * * アプリ名 : BG_SAMP.x * * BG表示のサンプル * * Ver1.00 * ******************************************************************************** * スプライトパレット0から15のうちパレット0はテキストパレットと共用。 * BGのパレットはスプライトと共用。 include A:\XC\INCLUDE\DOSCALL.MAC * OSコール用マクロの読み込み include A:\XC\INCLUDE\IOCSCALL.MAC * IOCS(BIOS)コール用マクロの読み込み * システム領域のアドレス cg_palette equ $E82000 * CG用パレットデータの先頭アドレス cg_buffer equ $C00000 * CG-VRAMの先頭アドレス cg_scroll_x equ $E80018 * CGスクロール X cg_scroll_y equ $E8001a * CGスクロール Y sp_palette equ $E82200 * スプライト用パレットデータの先頭アドレス sp_controll equ $EB0000 * スプライトスクロールレジスターの先頭アドレス sp_pattern equ $EB8000 * スプライトパターンデータの先頭アドレス pcg_area equ $EB8000 * SPRITEとBGのパターンデータの先頭アドレス bg_dataarea0 equ $EBC000 * BG画像0の先頭アドレス bg_dataarea1 equ $EBE000 * BG画像1の先頭アドレス bg_scroll_x0 equ $EB0800 * BG0のスクロールX座標 bg_scroll_y0 equ $EB0802 * BG1のスクロールY座標 bg_scroll_x1 equ $EB0804 * BG0のスクロールX座標 bg_scroll_y1 equ $EB0806 * BG1のスクロールY座標 vsync equ $E88001 * %00010000でV-Syncチェックする pad1 equ $E9A001 * ゲームパッド1 pad2 equ $E9A003 * ゲームパッド2 .cpu 68000 * CPUのタイプ .data * '.data'以降のデータはデータセクションに配置される scrolly0:dc.w 0 * BG0のY座標 bg01: dc.b $42,$22,$22,$24 dc.b $24,$44,$44,$43 dc.b $24,$44,$44,$43 dc.b $24,$44,$44,$43 dc.b $24,$44,$44,$43 dc.b $24,$44,$44,$43 dc.b $24,$44,$44,$43 dc.b $43,$33,$33,$34 sppal01: * GGGGG RRRRR BBBBB A dc.w %00000_00000_00000_0 dc.w %00000_00000_11111_0 dc.w %11000_11000_11000_0 dc.w %01000_01000_01000_0 dc.w %10000_10000_10000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %11111_11111_11111_0 .bss * '.bss'以降データバッファ .text * '.text'以降のプログラムはテキストセクションに配置される start: * スタートアドレス * カーソルをオフにする moveq.l #_OS_CUROF,d0 trap #15 * ランダム関数の初期化 move.l #23456,d0 * d0.lにランダムのシードを代入する dc.w $FE0D * ランダムのシードを設定する * ユーザーモードからスーパーバイザーモードに移行する moveq.l #_B_SUPER,d0 * d0にIOCS(BIOS)機能番号を代入 move.l #0,d1 * 数値0をd1に代入 movea.l d1,a1 * d1をa1にコピー trap #15 * IOCSコール実行 * 画面モードの設定 moveq.l #_CRTMOD,d0 * 画面モードの設定 move.w #10,d1 * 画面モードの番号 : 16 = 768x512x4bit / 10 = 256x256x8bit trap #15 * 画面をクリアして表示をオンにする moveq.l #_G_CLR_ON,d0 * 画面をクリアして表示をオンにする trap #15 * スプライト初期化 moveq.l #_SP_INIT,d0 trap #15 * スプライト表示をオンにする moveq.l #_SP_ON,d0 trap #15 * BG画面の設定 moveq.l #_BGCTRLST,d0 moveq.l #0,d1 * 0 = BG0 / 1 = BG1 moveq.l #0,d2 * 0 = テキストページ0 / 1 = テキストページ1 moveq.l #1,d3 * 0 = OFF / 1 = ON trap #15 moveq.l #_BGCTRLST,d0 moveq.l #1,d1 moveq.l #1,d2 moveq.l #1,d3 trap #15 bsr set_palette * スプライトパレット設定ルーチンの呼び出し bsr set_pcg * PCGパターンデータの定義ルーチンの呼び出し bsr init_bg * BG0にPCG画像を映す loop: * メインループ開始 * V-Syncビットを監視してメインループを60fpsで動作させるタイミングを取る movea.l #vsync,a0 vsync_1: move.b (a0),d0 and.b #$10,d0 tst.b d0 beq vsync_1 vsync_2: move.b (a0),d0 and.b #$10,d0 tst.b d0 bne vsync_2 * BG0の縦スクロール move.w scrolly0,d0 subi.w #1,d0 and.w #%00000001_11111111,d0 move.w d0,scrolly0 move.w d0,bg_scroll_y0 * [ESC]キーが押されたら終了処理'end:'にジャンプする moveq.l #_BITSNS,d0 moveq.l #0,d1 trap #15 and.b #%00000010,d0 tst.b d0 bne end bra loop * メインループの最初にジャンプする end: moveq.l #_CRTMOD,d0 move.w #16,d1 trap #15 * カーソルをオンにする moveq.l #_OS_CURON,d0 trap #15 * スーパーバイザーモードからユーザーモードに戻る moveq.l #_B_SUPER,d0 move.l SP,a1 trap #15 * アプリ終了 dc.w _EXIT * OSコール実行 : _EXIT = プログラムの終了 * RGBQUAD { Blue8, Green8, Red8, Reserved8 } = %RRRRRRRR_GGGGGGGG_BBBBBBBB_AAAAAAAA * palette { Green5, Red5, Blue5, Alpha1 } = %GGGGG_RRRRR_BBBBB_A * Set Sprite Palette set_palette: movea.l #sp_palette,a0 * スプライト用パレットレジスターアドレス adda.l #32,a0 lea sppal01,a1 * パレットデータバッファアドレス moveq.l #0,d7 set_palette_1: move.w (a1)+,(a0)+ addq.w #1,d7 * 色番号を次の番号に更新する cmp.w #16,d7 * 現在の色番号と16を比較する blt set_palette_1 * 現在の色番号が16未満ならアドレスset_palette_1に飛ぶ rts * 呼出元に戻る * PCGパターンの定義 set_pcg: lea bg01,a0 movea.l #pcg_area,a1 adda.l #32,a1 moveq.l #0,d7 set_pcg_1: move.l (a0)+,(a1)+ addq.w #1,d7 cmp.w #32/4,d7 blt set_pcg_1 rts put_pcg: * d0.w = 0 - 63 * X座標 * d1.w = 0 - 63 * Y座標 * d2.w = %V_H_00_CCCC_PPPPPPPP * PCG情報 * PCG情報 * V = 垂直反転 * H = 水平反転 * C = パレット番号 * P = PCG番号 movem.l d0-d1/a0,-(sp) movea.l #bg_dataarea0,a0 mulu #64,d1 add.w d0,d1 add.w d1,d1 add.l d1,a0 move.w d2,(a0) movem.l (sp)+,d0-d1/a0 rts init_bg: move.w #$0101,d2 moveq.l #0,d1 init_bg_1: moveq.l #0,d0 init_bg_2: bsr put_pcg addq.w #1,d0 cmp.w #64,d0 blt init_bg_2 addq.w #1,d1 cmp.w #64,d1 blt init_bg_1 rts ------------------------------------------------------------------------------------------------ コマンドプロンプトから、 A>as BG_SAMP.s [Enter] A>lk BG_SAMP.o [Enter] A>BG_SAMP.x [Enter] のように入力するとBG画面がスクロールします。 終了は[ESC]キーです。 [ BG/PCG ] < PCG/BGデータのアドレス配置 > ---------------------------------------------------------------- 配置タイプ (A) (B) (C) $EB8000 ---------------- ---------------- ---------------- PCGエリア PCGエリア PCGエリア | 8×8px |共 | 8×8px |共 | 8×8px |共 | 16×16px |用 | 16×16px |用 | 16×16px |用 $EBA000 ---------------- ---------------- ---------------- PCGエリア PCGエリア PCGエリア 16×16px専用 16×16px専用 16×16px専用 $EBC000 ---------------- BGデータエリア0 $EBE000 ---------------- ---------------- BGデータエリア1 BGデータエリア1 $EBFFFE ---------------- ---------------- ---------------- ---------------------------------------------------------------- この3種類(配置タイプA〜C)のPCGメモリー空間から一つを選んで それに従ったデータ配置をして画面を構築します。 今回のサンプルプログラムの解像度が256×256ピクセルなので PCGの1個のサイズは8×8ピクセルになります。 PCGは4ビットカラーなので1個あたり32バイトです。 定義できるPCGは最大256個です。 PCGエリアはスプライトパターンデータと共用です。 BG画面はPCGが縦横それぞれ64個ぶんの大きさで(512×512ピクセル)、 その中の256×256ピクセルがモニターに表示されます。 BG画面は最大2枚重ねて表示できます。 一つのBGデータエリアに対して横64個縦64個のPCGが割り当てられます。 ここまで読んできて解り辛いと思った方も沢山いらっしゃると思います。 そういう訳で別の説明の仕方で書いていこうと思います。 [=> こう説明を追加すると解りやすいかな? <=] BG画面は昔のRPGゲームのマップ画面だと思って下さい。 昔は8×8ピクセルのマップを構成する小さな画像を チップとかブロックと呼んでましたよね? チップやブロックをX68000ではPCGと呼びます。 BG画面はこのチップが横64個縦64個で構成されています。 チップをBG画面に置くにはBGデータエリアの指定の場所に 「%V_H_00_CCCC_PPPPPPPP」の16ビットデータ(以後チップデータ)を置きます。 %V = 縦方向に反転をするかしないか1ビット %H = 横方向に反転をするかしないか1ビット %C = パレット番号を4ビット %P = 表示するチップの番号を8ビット 置くチップの情報は以上のとおりです。 希望の位置にチップデータを置くときの場所(メモリーアドレス)の求め方は、  address = ( ( 64 × Y ) + X ) × 2 + ( BGデータエリア先頭アドレス ) となります。 (式中に「 × 2 」とある理由はチップデータのサイズが2byte(16ビット)だからです。) 僕なりに解りやすく説明を書いて来ましたが これでBG画面を理解して頂けたら幸いです。 今回はこれにて失礼します。 お疲れ様でした!! [EOF]